home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Micro R&D 5: Mand 2000
/
Mand 2000 - Micro R&D CD-ROM Vol 5.iso
/
bonusstuff
/
mandtopi.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-09-12
|
10KB
|
244 lines
/*
MandToPi.c - Copyright © 1993 CygnusSoftware.
Cygnus Software
33 University Square, #199
Madison, WI, 53715
USA
CygnusSoft@cup.portal.com
This program is supplied along with Mand2000, the tryware fractal
exploration program for the Amiga. Mand2000 features multi-pass drawing,
animated zooming, joystick driving through the Mandelbrot set, full ARexx
support, 1000+ bit accuracy, multiple fractal equations, etc. 68000
required. MandToPi and Mand2000 may not be distributed, but may be
purchased from Cygnus Software for $34.95. Demo versions of Mand2000 are
available on many networks.
MandToPi is based on a discovery made by Dave Boll in 1991.
Boll's rather surprising discovery was that that ubiquitous number, PI,
could even be found in the Mandelbrot set. Where? Well, if you look at
the two largest bulbs of the Mandelbrot set (the head and body) you might
notice that these bulbs are seperated by two spikes or arrows. One spike
on either side. And you may wonder how close do those two spikes get to
each other? How thin is the `neck' of the Mandelbrot? Since the
Mandelbrot set is known to be connected (all those black areas are tied
together by microscopic black filaments) the spikes can't actually touch.
But if they don't touch, how close do they get? As it turns out they get
infinitely close - that is, there is just a single mathematical point
separating the two spikes.
The `real' coordinate of those spikes (also known as the x coordinate)
is -0.75, a nice round number. What this program does is it tries a series
of points, all with real coordinates of -0.75, but each one a tiny bit
closer to the real axis. For each point it calculates the number of
iterations it takes for that point to escape. All of these points will
escape, because all of the points are on the spikes and therefore not in
the Mandelbrot set.
What Boll's discovery was is that there is a very strange pattern to
the number of iterations. Each point we try is one tenth the distance to
the real axis, and each number of iterations that the program prints out
looks more and more like PI! In fact, the general rule is that if you take
the point (-.75, E), where E is any small number (less than one), then the
number of iterations until that point escapes,, times E, is approximately
equal to PI. The smaller E gets, the closer the approximation. In fact,
the error is always less than E, so in theory you can get an arbitrarily
accurate value for PI, although to get more than seven or eight digits
takes a phenomenal amount of computing time.
Here's the results from a ten pass run of this program. This run took
five hours on an '040 - not surprising as over thirty billion floating
point operations were involved.
E is 1.00000000000, num iterations is 3, PI is ~3.00000000000
E is 0.10000000000, num iterations is 33, PI is ~3.30000000000
E is 0.01000000000, num iterations is 315, PI is ~3.15000000000
E is 0.00100000000, num iterations is 3143, PI is ~3.14300000000
E is 0.00010000000, num iterations is 31417, PI is ~3.14170000000
E is 0.00001000000, num iterations is 314160, PI is ~3.14160000000
E is 0.00000100000, num iterations is 3141593, PI is ~3.14159300000
E is 0.00000010000, num iterations is 31415927, PI is ~3.14159270000
E is 0.00000001000, num iterations is 314159266, PI is ~3.14159266000
E is 0.00000000100, num iterations is 3141592656, PI is ~3.14159265600
The final digit is sometimes off by a bit, but the other digits are
always correct. Strange things these fractals. Strange stuff math. You
just can't keep a good number down.
The actual value of PI, to more digits that you'll ever need is:
3.1415926535 8979323846 2643383279 5028841971 6939937510 5820974944...
This was NOT calculated with this program. Don't even try.
For the more graphically oriented, you may want to explore these spikes
with Mand2000. However if you aren't careful in your exploration, you may
be disappointed. The first important thing to do is to make sure that
Sneaky pixels (in the Setup/Set misc menu) is turned off. Next, because
the spikes are very thin and can easily sneak between two columns of
pixels, you must have the pixels on your monitor lined up so that there is
a column of pixels at exactly -0.75. The best way to deal with this is to
zoom in a bit and then scroll the picture so that the two spikes are quite
close to the left edge of the screen. Then bring up the `Set location'
requester and type in -0.75 for the left coordinate. Now, even when you
scroll the spikes back to the centre of the screen, or zoom in, there will
still be a column of pixels precisely lined up on the spikes. This makes
it much easier to see how close to each other the spikes really get. The
next step is to increase the number of iterations as high as possible. The
final thing to do is to crank up the accuracy a bit - go into the Setup
in the Misc menu and set extra accuracy to about four. Normally Mand2000
tries to get away with as little accuracy as possible, for speed reasons,
but for calculations like this, precise results need a few more digits.
All this should insure that your results will not be severely degraded.
The source to this program was provided so that mathematical explorers
can search around and find other places in the Mandelbrot set where PI
occurs. It can also be found, for instance, at the `butt' of the
Mandelbrot set, but I'll leave the exact method as an exercise for the
reader.
To find out more about Boll's discovery, read "Fractals for the
Classroom - Part Two", an excellent book for anybody interested in learning
wierd and wonderful facts about these beatiful monsters.
When compiling this program be sure to compile with a very accurate
floating point option. The `Fast Floating Point' (FFP) routines are not
accurate enough and will cause the program to run forever. If you have an
FPU, compile and link with the FPU options, because they are both very fast
and very accurate. And be sure to link with the appropriate floating point
library, needed to print out the results. */
#include <stdio.h>
#define AMIGA
#ifdef AMIGA
/* The special code is necessary for the Amiga to allow this program to */
/* be run from the workbench, where a console window must be opened and */
/* Ctrl-C won't stop the program. */
#include <clib/exec_protos.h>
#include <dos/dosextens.h>
#endif
/* This may be an Aztec specific function - replace it with your own or */
/* just comment it out. It just checks for control C and exits when it */
/* detects it. */
long Chk_Abort(void);
/*
Warning. Set this to higher numbers at your own risk. Even at just
seven, the final pass will do 3,141,593 iterations - which takes a few
seconds even on an '040. Each time you increment NUMPASSES, it does
ten times as many iterations - if you set it to ten you can expect your
computer to be busy for several hours at least.
*/
#define MAXPASSES 10
/*
For those hard core experimenters who want to try multi-week runs, I've
made counter into a long double instead of a mere long. This will allow
maximum counts of somewhere around 16 billion billion instead of only four
billion. (Half of you will probably complain that a long double can go
much higher than that - but it can't if you still want to be able to
accurately add one to it). However, after that many iterations, it is
unlikely that enough accuracy will be left to continue giving you more
digits of PI. That's chaos for you.
*/
int main(int argc, char *argv[])
{
register long double zr, zi, cr, ci;
register long double rsquared, isquared;
register long double counter;
long double starti;
register short abortcounter;
short pass;
FILE *mystdout;
unsigned short breakable;
#ifdef AMIGA
struct Process *myprocess;
myprocess = (struct Process *)FindTask(NULL);
if (!(myprocess->pr_ConsoleTask))
{
mystdout = fopen("con:0/0/640/150/Pi from the Mandelbrot set./Wait/Auto/Close", "w");
breakable = FALSE;
}
else
#endif
{
mystdout = stdout;
breakable = TRUE;
}
fprintf(mystdout, "MandToPi: Copyright © 1993 Cygnus Software.\n");
fprintf(mystdout, "Calculating PI based on escape times from the `neck' at (-0.75, 0.0) of\n");
fprintf(mystdout, "the Mandelbrot set. Read the file 'MandToPI.c' for more information.\n");
fprintf(mystdout, "\n");
if (breakable)
{
fprintf(mystdout, "Type Ctrl-C to stop.\n");
fprintf(mystdout, "\n");
}
/* The initial value for starti and the amount to reduce it by are quite */
/* arbitrary. You could just as easily start at 0.683 and multiply by */
/* 0.5 each time instead. PI is unavoidable. */
for (starti = 1.0, pass = 0; pass < MAXPASSES && (breakable || pass < 5); starti *= 0.1, pass++)
{
zr = 0.0;
zi = 0.0;
cr = -.75;
ci = starti;
rsquared = zr * zr;
isquared = zi * zi;
/* The guts of the program - standard Mandelbrot iteration formula. */
for (counter = 0; rsquared + isquared <= 4.0; counter++)
{
zi = zr * zi * 2;
zi += ci;
zr = rsquared - isquared;
zr += cr;
rsquared = zr * zr;
isquared = zi * zi;
if (breakable)
if (!((++abortcounter) & 0xFF))
Chk_Abort();
}
/* To make the results look pretty, be sure to put .N, where is N is MAXPASSES or greater */
/* after each percent sign in the following printf control string. Otherwise you may get */
/* misaligned printouts or, worse, missing digits. */
fprintf(mystdout, "E is %.11Lf, num iterations is %11.Lf, PI is ~%.11Lf\n", starti, counter, starti * counter);
}
fprintf(mystdout, "\nDone.\n");
#ifdef AMIGA
if (!(myprocess->pr_ConsoleTask))
{
fprintf(mystdout, "Run from the CLI to see a longer run.\n");
fclose(mystdout);
}
#endif
return 0;
}